package paint;

import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;

public abstract class PaintComponent {
	/**
	 * Normal behavior. The isPressed() method returns true as long as the key
	 * is held down.
	 */
	public static final int NORMAL = 0;
	protected final PaintUtils paintUtils = new PaintUtils();

	/**
	 * Initial press behavior. The isPressed() method returns true only after
	 * the key is first pressed, and not again until the key is released and
	 * pressed again.
	 */
	public static final int DETECT_INITAL_PRESS_ONLY = 1;

	private static final int STATE_RELEASED = 0;
	private static final int STATE_PRESSED = 1;
	private static final int STATE_WAITING_FOR_RELEASE = 2;

	private int behavior;
	private int amount;
	private int state;

	protected Rectangle bounds;

	public PaintComponent(Rectangle bounds) {
		this.bounds = bounds;
	}

	public PaintComponent() {
		super();

		bounds = new Rectangle(0, 0, 0, 0);
	}

	public Rectangle getBounds() {
		return bounds;
	}

	public int getX() {
		return bounds.x;
	}

	public int getY() {
		return bounds.y;
	}

	public int getWidth() {
		return bounds.width;
	}

	public int getHeight() {
		return bounds.height;
	}

	public void setLocation(int x, int y) {
		bounds.x = x;
		bounds.y = y;
	}

	/**
	 * Resets this component so that it appears like it hasn't been pressed.
	 */
	public void reset() {
		state = STATE_RELEASED;
	}

	/**
	 * Taps this component. Same as calling press() followed by release().
	 */
	public synchronized void tap() {
		press();
		release();
	}

	/**
	 * Signals that the key was pressed.
	 */
	public synchronized void press() {
		press(1);
	}

	/**
	 * Signals that the key was pressed a specified number of times, or that the
	 * mouse move a spcified distance.
	 */
	public synchronized void press(int amount) {
		if (state != STATE_WAITING_FOR_RELEASE) {
			this.amount += amount;
			state = STATE_PRESSED;
		}

	}

	/**
	 * Signals that the key was released
	 */
	public synchronized void release() {
		state = STATE_RELEASED;
	}

	/**
	 * Returns whether the key was pressed or not since last checked.
	 */
	public synchronized boolean isPressed() {
		return getAmount() != 0;
	}

	public synchronized int getAmount() {
		int retVal = amount;
		if (retVal != 0) {
			if (state == STATE_RELEASED) {
				amount = 0;
			} else if (behavior == DETECT_INITAL_PRESS_ONLY) {
				state = STATE_WAITING_FOR_RELEASE;
				amount = 0;

			}
		}

		return retVal;
	}

	public abstract void paint(Graphics g);

	public void mouseEvent(MouseEvent mouse) {
		int id = mouse.getID();
		switch (id) {
		case MouseEvent.MOUSE_PRESSED:
			press();
			mousePressed(mouse);
			return;
		case MouseEvent.MOUSE_RELEASED:
			release();
			mouseReleased(mouse);
			return;
		case MouseEvent.MOUSE_DRAGGED:
			mouseDragged(mouse);
			return;
		case MouseEvent.MOUSE_ENTERED:
			mouseEntered(mouse);
			return;
		case MouseEvent.MOUSE_EXITED:
			mouseExited(mouse);
			return;
		}
	}

	public abstract void mousePressed(MouseEvent e);

	public abstract void mouseReleased(MouseEvent e);

	public abstract void mouseClicked(MouseEvent e);

	public abstract void mouseEntered(MouseEvent e);

	public abstract void mouseExited(MouseEvent e);

	public abstract void mouseDragged(MouseEvent e);
}
